package cn.tedu.icop.finance.service.impl;
import cn.tedu.icop.finance.dao.repository.ChargingDataRepository;
import cn.tedu.icop.finance.dao.repository.ChargingRuleRepository;
import cn.tedu.icop.finance.dao.repository.CostRuleCacheRepository;
import cn.tedu.icop.finance.pojo.po.ChargingDataPO;
import cn.tedu.icop.finance.pojo.po.CostRulePO;
import cn.tedu.icop.finance.service.CostService;
import cn.tedu.icop.api.domain.ChargingProcessParam;
import cn.tedu.icop.api.domain.ChargingProcessVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;

@Slf4j
@Service
public class CostServiceImpl implements CostService {
    @Autowired
    private ChargingRuleRepository chargingRuleRepository;
    @Autowired
    private CostRuleCacheRepository costRuleCacheRepository;
    @Autowired
    private ChargingDataRepository chargingDataRepository;

    /**
     * 价格计算
     * 1 计算一次的价格
     *  1.1 计价规则
     * 2 价格的累加
     * @param chargingProcessParam
     * @return
     */
    @Override
    public ChargingProcessVO calculateCost(ChargingProcessParam chargingProcessParam) {
        //1.从ES获取充电时序数据
        ChargingDataPO chargingDataPO = chargingDataRepository.findByOrderNo(chargingProcessParam.getOrderNo());
        if(chargingDataPO==null){
            chargingDataPO = new ChargingDataPO();
            BeanUtils.copyProperties(chargingProcessParam,chargingDataPO);
            chargingDataPO.setCount(1);
            chargingDataPO= chargingDataRepository.save(chargingDataPO);
        }
        //2.获取匹配的计价规则
        CostRulePO matchedCostRule=getMatchCostRule(chargingProcessParam);
        //3.进行费用计算
        if(matchedCostRule!=null){
            if(chargingDataPO.isFirst()){
                doFirstCost(chargingProcessParam,chargingDataPO,matchedCostRule);
            }else{
                doLastCost(chargingProcessParam,chargingDataPO,matchedCostRule);
            }
        }else{
            log.error("场站{}在{}没有匹配到对应的计费规则",chargingProcessParam.getStationId(),LocalDateTime.now());
        }
        //4.封装结果并返回
        ChargingProcessVO chargingProcessVO = new ChargingProcessVO();
        BeanUtils.copyProperties(chargingDataPO,chargingProcessVO);
        return chargingProcessVO;
    }
    private void doFirstCost(ChargingProcessParam chargingProcessParam,ChargingDataPO chargingDataPO, CostRulePO matchedCostRule){
        //获取截止到当前时间已充电的总度数
        Float chargingCapacity = chargingProcessParam.getChargingCapacity();
        //进行价格计算[(电单价+服务费)*充电量]
        BigDecimal add = matchedCostRule.getPowerFee().add(matchedCostRule.getServiceFee());
        BigDecimal multiply = add.multiply(BigDecimal.valueOf(chargingCapacity));
        //更新ES中存储的数据
        chargingDataPO.setChargingCapacity(chargingCapacity);
        chargingDataPO.setTotalCost(multiply);
        chargingDataRepository.save(chargingDataPO);
    }
    private void doLastCost(ChargingProcessParam chargingProcessParam,ChargingDataPO chargingDataPO, CostRulePO matchedCostRule){
        //获取截止到当前时间已充电的总度数
        Float chargingCapacity = chargingProcessParam.getChargingCapacity();
        chargingDataPO.setCount(chargingDataPO.getCount()+1);
        //进行价格计算[(电单价+服务费)*充电量]
        BigDecimal subtractChargingCapacity =
                BigDecimal.valueOf(chargingCapacity).subtract(BigDecimal.valueOf(chargingDataPO.getChargingCapacity()));
        BigDecimal add = matchedCostRule.getPowerFee().add(matchedCostRule.getServiceFee());
        BigDecimal multiply = add.multiply(subtractChargingCapacity);
        //更新ES中存储的数据
        chargingDataPO.setChargingCapacity(chargingCapacity);
        chargingDataPO.setTotalCost(multiply);
        chargingDataRepository.save(chargingDataPO);
    }

    /**
     * 获取计价规则
     * @param chargingProcessParam
     */
    private CostRulePO getMatchCostRule(ChargingProcessParam chargingProcessParam) {
        //1.获取所有充电规则
        List<CostRulePO> costRules = costRuleCacheRepository.getCostRuleByStationId(chargingProcessParam.getStationId());
        if(costRules==null){
            costRules = chargingRuleRepository.selectCostRules(chargingProcessParam.getStationId());
            costRuleCacheRepository.saveCostRule(chargingProcessParam.getStationId(),costRules);
        }
        //2.进行充电规则匹配
        //2.1获取当前时间
        int nowHour = LocalDateTime.now().getHour();
        //2.2进行规则匹配
        CostRulePO matchedCostRule = null;
        for(CostRulePO costRulePO:costRules){
            if(nowHour>=costRulePO.getStartTime()&&nowHour<=costRulePO.getEndTime()){
                if(costRulePO.getGunType()== chargingProcessParam.getGunType()){
                    matchedCostRule= costRulePO;
                    break;
                }
            }
        }
        return matchedCostRule;
    }
}
